أدرة المستخدمين والملفات
لدى الملف أسم وبعض الخصائص تسمى "المعلومات الإدارية" administrative information التي من ضمنها إنشاء الملف والتعديل والصلاحيات ، وتخزن هذة الخصائص في inode الملف ، البلوك الخاصة من البيانات في نظام الملف file system التي ايضاً تحتوي الطول الملف وحيث أن على القرصة خزن ، يستعمل النظام عدد inode الملف ، وتركيب المجلدات هو فحسب أسماء الملف لمنفعتنا ، اي ان المجلد هو ملف يمسك أرقام inode واسماء الملفات الاخرى ، ولكل مدخل entry مجلد فهو مربوط link الى inode الملف ، وبحذف أسم الملف نستطيع حذف مايتربط بة أو مجلدة عن طريق الامر ln ( نرى أرقام inode للملف بإستعمال الامر ln –i ) ونستطيع ان نجعل رابط للنفس الملف في مختلف المجلدات.
directory
التي هي أنواع خاصة من الملفات
توفر البيرل بعض الدوال للحصول على معلومات المستخدام على بيئة اليونكس كالـدالة getpwent و getgrent المشتقة أساساً من مكتبة الدوال للسي التي ايضاً بنفس الاسم ، تؤدي جميع أرصفة اليونكس نفس العمل بإدراة المستخدمين والمجموعات لكن بعض الشيء قد تتفأوت المعلومات المخزنة الاظافية بينما تعمل البيرل على توحيد كل الإختلافات في أرصفة اليونكس من نظام الى اخر ويوجد حول هذا الشأن في مستندات النظام كمصدر للمعلومات على القيم التي تعيدها هذة الدوال .
يضع نظام اليونكس معلومات المستخدم والمجموعة في ملفات /etc/passwd و /etc/group ، يمكن قراءت الملفات من قبل جميع المستخدمين ولربما يشكل هذا تهديد أمني ، لغرض الحماية عند مشاهدة معلومات المستخدم والمجموعة تصبح كلمات السر مضللة shadow في الإستخدام بمعنى أن معلومات المستخدم في /etc/passwd لان تحتوي على الباسورد المشفرة في حقل كلمة السر للملف ، كذلك في حال وضع اعداءدات خاصة للسورسات ولمعلومات المستخدم والمجموعة من قبل المالك ( كالـ NIS أو NIS+ ) فأن طلب معلومات المستخدم والمجموعة تبدأ بعمل lookup للشبكة ثم تسترجع المعلومات من الخادم البعيد وبتلك فطلب ملفات المعلومات في أي من المحلية أو البعيدة تكون راجعة ومعرفة في ملف /etc/nsswitch.conf (وهو ملف عام يتحكم باولويات الربط للمضيفين او DNS server راجع كتاب مؤيد الصفحة الثالثة ) .
يوجد ايضاً دعم لبعض اشكال الحماية الاخرى الغير مزودة بالدوال الداخلية من خلال الوحـدات الممتدة فمثلاً الونيدوز والأرصفة الاخرى غير اليونكس لاتدعم إي من الدوال getpwent او getgrent مع ذلك فأن بيئة Cygwin تزود هذة الوظائف بشكل أمان وضمن حدود لإستخدام هذة الدوال كوحـدة Win32::AdminMisc للوصول الى Win32 Security API ، وكذلك قائمة التحكم بوصول المستخدمين عبر Access Control Lists (ACLs) وأساليب الحماية المتقدمة الاخرى خارج متناول هذة الدوال الداخلية (حتي في اليونكس) ولكنهم يمكن ان يعالجوا عن طريق مختلف الوحـدات المختلفة المتوفرة من CPAN .
معلومات المستخدم
تخزن كما سبق معلومات المستخدم على أرصفة اليونكس في ملف passwd والصيغة تتفاوت بعض الشيء في هذا الملف من نظام الى اخر:
fred:RGdmsaynFgP56:301:200:Fred A:/home/fred:/bin/bash
jim:Edkl1y7NMtO/M:302:200:Jim B:/home/jim:/bin/ksh
mysql:!!:120:120:MySQL server:/var/lib/mysql:/bin/csh
يحتوي السطر من حقول (اسم المستخدم ، كلمة المرور ، uid الرقم المحدد لكل مستخدم ، gid رقم المجموعة التي ينتمي اليها ، معلومات اضافية عن المستخدم ، البيت الخاص بالمستخدم ، الشل المحددة ) في هذة الحالة لايتأثر ملف كلمة السر المضلل shadow لذلك فأن حقل كلمة السر متضمنة ومشفرة ، وعند النظر الى حقل المستخدمين نجد في أول سطرين مستخدمين عادين بينما الثالث معرف لخادم قاعدة البيانات MySQL للإشتغال عبرة والتي لان تحتاج الى كلمة المرور للدخول المستخدم ويعني ان كلمة المرور غير ممكنة مع !! ولم توضع له باسورد حتى الان( وكذلك الرمز * يستعمل لهذا الغرض أحياناً ) .
تسترجع الدالة getpwent مدخلاً واحداً (الكلمة “password entry”اختصارها pwent) من ملف معلومات المستخدم وتبدأ من أول سطر ، وفي حالة كان السياق قائمة فسوف تعيد ليس على الاكثر من عشرة حقول :
($name, $passwd, $uid, $gid, $quota, $comment, $gcos, $dir, $shell, $expire)
= getpwent;
فشكل معلومات المستخدم متفاوتة وليس جميع الحقول معرفة في مختلف الأرصفة كذلك المعلومات الراجعة متقاربة مع الحقول الموجودة في السابق وبعضهم يعدل المعني ، وفي الجدول التالي اسفل جميع الحقول والمعنى لكل حقل منهم ،شاهدة صفحة ملف passwd عن طريق الامر man 5 passwd لتفصيل المنجز على المعطى منهم
|
الحقل |
المعنى |
| 0 |
name |
اسم المستخدم |
| 1 |
passwd |
كلمة المرور مشفرة ، يعتمد التشفير على الرصيف فقد يكون مشفر بإستعمال دالة اليونكس القياسية crypt أو اكثر حماية مع خوارزمية MD5 hashing ، وفي حالة عمل ملف الباسورد المضلل shadow فأن الحقل يعاد مع علامة النجمة * ، إظافة الى ذلك عند تحديد ! في مقدمة كلمات المرور فذلك يعني عدم تمكين الحسابات |
| 2 |
uid |
user ID رقم معرف المستخدم |
| 3 |
gid |
group ID رقم معرف المجموعة التي ينتمي اليها المستخدم |
| 4 |
quota |
السعة الذي يستغرقها هذا المستخدم من القرص ، والحقل ليس مدعوم على أكثر الانظمة وقد يوضع بدلاً عنة حقل التغير او العمر |
| 5 |
comment |
تعليق المستخدم مثلاً الاسم الكامل وبعض المعلومات عن المستخدم ، وقد يأتي بدلاً عنة على بعض الانظمة حقل class ، ويسمى ايضاً حقل التعليق بالحقل gcos لكن ليست اتم بالمعني الذي ماسيحتوية الحقل التالي . |
| 6 |
gcos |
تعرف ايضاً بالـ GECOS اختصار “General Electric Computer Operating System” ويعتبر تعليق ممتد للمستخدم فمثلاً الاسم ومن أين والعمل ورقم تلفون العمل ...الى غير ذلك من المعلومات |
| 7 |
dir |
مجلد البيت الخاصة بالمستخدم home directory |
| 8 |
shell |
شل الدخول للمستخدم مثلاً /usr/bin/bash |
| 9 |
expire |
تأريخ إنتهاء حساب المستخدم ، غير مدعومة هذة الخاصية كثيراً وفي أغلب الاحيان غير معرفة. |
تعيد الدالة getpwent في سياق scalar أسم المستخدم في السطر فمثلاً لجلب جميع أسماء المستخدمين :
#!/usr/bin/perl
# listusers.pl
use warnings;
use strict;
my @users;
while (my $name = getpwent) {
push @users, $name;
}
print "Users: @users \n";
قد تأتي الدوال setpwent و endpwent مع الدالة getpwent، تهتم الدالة setpwent بأعادة مؤشر السجل التالي المعاد بواسطة getpwent الى بداية الملف passwd ، التي هي مماثلة للدالة rewinddir بالطريقة نفسها ، كذلك getpwent تعمل ايضاً بشكل مماثل للدوال opendir و readdir مجتمعة معاً ، ولانة لا يوجد سواء ملف passwd واحد فقط لذلك هي لاتأخذ اي وسيط :
setpwent;
الـدالة endpwent مماثلة للـدالة closedir التي تغلق مؤشر الملف الداخلي المنشأ حينما إستخدامنا الدالة getpwent ( او مع دوال getpwnam/getpwuid ) ، فلا نستطيع الوصول الى مقبض الملف الداخلي لكنة قد يحرر لكي يسترد أو يعيد السيطرة للمصادر المستهلكة لإستعمال مرة اخرى ، بالإظافة عند طلب المعلومات عبر شبكة فذلك سوف يغلق الإتصال :
endpwent;
هناك ايضاً الدالتين getpwnam و getpwuid للروية الأسماء والمعرفات IDs مع بعضهم البعض ، تقوم الدالة getpwnam بأخذ اسم المستخدم كوسيط وتعيد user ID في سياق scalar أو في قائمة كاملة من العشر الحقول في حالة سياق قائمة :
$uid = getpwnam($username);
@fields = getpwnam($username);
الدالة getpwuid مماثلة فهي تأخذ الـuser ID العددي وتعيد أما الاسم أو قائمة الحقول يعتمد ذلك على السياق :
$username = getpwuid($uid);
@fields = getpwuid($uid);
وكلتا الدالتين لها نفس تأثير setpwent حيث تعيد موقع المؤشر المستعمل بواسطة getpwent ولذلك فهم لايمكن ان تجتمع مع التكرارات .
توفر البيرل الموديل User::pwent لإدارة السهلة للمستخدمين ولحقول العشرة ،وتنجز هذة الموديل التفاعل بواسطة الكائنات الموجهه للدوال pw ، وتوفر الموديل User::grent لمعلومات المجموعة وكذلك الموديل Net::hostent, Net::servent, Net::netent, Net::protoent لمعلومات الشبكة ، وايضاً Stat للحالة (عبر الدوال stat and lstat )
تقوم وحـدة User::pwent بعمل تحميل زائد للدوال getpwent, getpwnam, getpwuid الداخلية عند استخدامها وتعيد الكائن pw مع الطرق ، جميع الطرق تعطي الحقول المتعلقة بها ، وايضاً طريقة الصنف pw_has لتقدير الحقول المدعمة وغير مدعمة ، فمثلاً لإستخدام getpwent مع وحـدة User::pwent :
#!/usr/bin/perl
# listobjpw.pl
use warnings;
use strict;
use User::pwent qw(:DEFAULT pw_has);
print "Supported fields: ", scalar(pw_has), "\n";
while (my $user = getpwent) {
print 'Name : ', $user->name, "\n";
print 'Password: ', $user->passwd, "\n";
print 'User ID : ', $user->uid, "\n";
print 'Group ID: ', $user->gid, "\n";
# one of quota, change or age
print 'Quota : ', $user->quota, "\n" if pw_has('quota');
print 'Change : ', $user->change, "\n" if pw_has('change');
print 'Age : ', $user->age, "\n" if pw_has('age');
# one of comment or class (also possibly gcos is comment)
print 'Comment : ', $user->comment, "\n" if pw_has('comment');
print 'Class : ', $user->class, "\n" if pw_has('class');
print 'Home Dir: ', $user->dir, "\n";
print 'Shell : ', $user->shell, "\n";
# maybe gecos, maybe not
print 'GECOS : ',$user->gecos,"\n" if pw_has('gecos');
# maybe expires, maybe not
print 'Expire : ', $user->expire, "\n" if pw_has('expire');
# separate records
print "\n";
}
أن استدعيت بدون وسطاء فأن طريقة الصنف pw_has سوف تعيد قائمة الحقول المدعمة في سياق قائمة بإظافة الى فصل النصوص بواسطة المسافة ،وبإستخدام التاج :DEFAULT لإستيراد القائمة الأفتراضية ويمكن أيضاً استيراد المتغيرات لكل حقل لكي تتجاهل أستدعاءات الطرق بإظافة التاج :FIELDS ( التي ايضاً متضمنة مع :DEFAULT) للإستيراد القائمة ، عموماً مجموعة المتغيرات مع الأسماء نفسها لطرقها ويعني انها مساوي مع تقديم pw_ امامها وبتعديل بسيط على البرنامج السابق المكتوب بإستعمال متغيرات الحقل
#!/usr/bin/perl
# listfldpw.pl
use warnings;
use strict;
use User::pwent qw(:FIELDS pw_has);
print "Supported fields: ", scalar(pw_has), "\n";
while (my $user = getpwent) {
print 'Name : ', $pw_name, "\n";
print 'Password: ', $pw_passwd, "\n";
print 'User ID : ', $pw_uid, "\n";
print 'Group ID: ', $pw_gid, "\n";
# one of quota, change or age
print 'Quota : ', $pw_quota, "\n" if pw_has('quota');
print 'Change : ', $pw_change, "\n" if pw_has('change');
print 'Age : ', $pw_age, "\n" if pw_has('age');
# one of comment or class (also possibly gcos is comment)
print 'Comment : ', $pw_comment, "\n" if pw_has('comment');
print 'Class : ', $pw_class, "\n" if pw_has('class');
print 'Home Dir: ', $pw_dir, "\n";
print 'Shell : ', $pw_shell, "\n";
# maybe gcos, maybe not
print 'GCOS : ', $pw_gecos, "\n" if pw_has('gecos');
# maybe expires, maybe not
print 'Expire : ', $pw_expire, "\n" if pw_has('expire');
# separate records
print "\n";
}
في المثال السابق يتم عمل overrides للمتغيرات الافتراضية ، لذلك اذا اردت إستيراد بعض المتغيرات دون الإستيراد الأفتراضي يجب عليك إستيراد الدول التي تريد عمل لها override :
use User::grent qw($pw_name $pw_uid $pw_gid getpwnam);
ولإستدعاء الدوال getpwent, getpwnam, and getpwuid الأصلية نستعمل الـCORE:: في المقدمة ، ومن الممكن ان نعمل قمع(suppress) للـoverrides الافتراضية وذلك من خلال مرور قائمة إستيراد فارغة أو ان تحتوي القائمة على :DEFAULT او :FIELDS ،فعلى سبيل المثال هتا نسخة اخرى للإسكربتات السابقة عن طريق وضع طريقة للكائن الجديد has لحزمة Net::pwent ، ثم تستعمل تلك وتستدعئ طريقة الصنف فقط ، ويتفادءى كل الإستيرادات :
#!/usr/bin/perl
# listcorpw.pl
use warnings;
use strict;
use User::pwent();
sub User::pwent::has {
my $self = shift;
return User::pwent::pw_has(@_);
}
print "Supported fields: ", scalar(User::pwent::has), "\n";
while (my $user = User::pwent::getpwent) {
print 'Name : ', $user->name, "\n";
print 'Password: ', $user->passwd, "\n";
print 'User ID : ', $user->uid, "\n";
print 'Group ID: ', $user->gid, "\n";
# one of quota, change or age
print 'Quota : ', $user->quota, "\n" if $user->has('quota');
print 'Change : ', $user->change, "\n" if $user->has('change');
print 'Age : ', $user->age, "\n" if $user->has('age');
# one of comment or class (also possibly gcos is comment)
print 'Comment : ', $user->comment, "\n" if $user->has('comment');
print 'Class : ', $user->class, "\n" if $user->has('class');
print 'Home Dir: ', $user->dir, "\n";
print 'Shell : ', $user->shell, "\n";
# maybe gcos, maybe not
print 'GECOS : ', $user->gecos, "\n" if $user->has('gecos');
# maybe expires, maybe not
print 'Expire : ', $user->expire, "\n" if $user->has('expire');
# separate records
print "\n";
}
لدى وحـدة Net::pwent الدالة getpw التي تأخذ أما أسم المستخدم أو المعرف ID ويعاد كائن user بإي منهم ، فأن الوسيط عددي فأن الدالة getpwuid لعمل العمل ، وغير ذلك فأن getpwnam من تسدعى .
$user = getpw($user_name_or_id);
معلومات المجموعة
لكل مستخدم مجموعة ينتمي اليها وقد يشترك المستخدم في أكثر من مجموعة وتوضع هذة المعلومات في ملف /etc/group مثلاً أسماء المجموعة ومعرفات المجموعة التي يمكن إستخراجها من الدوال getgrent, getgrnam, getgrgid المماثلة للدوال getpwent, getpwnam, getpwuid عند التعامل مع ملف /etc/passwd سابقاً ، الدالة getgrent تقرأ مدخل واحد من ملف group في كل مرة تستدعى بدايتاً من المدخل الاول ويعاد المدخل التالي عند العودة .وتعيد أربعة حقول وهم أسم المجموعة ، وكلمة المرور (عادتاً لا تحدد) ، و معرف المجموعة group ID or gid ، ومن هم المستخدمين الاعضاء في هذة المجموعة
#!/usr/bin/perl
# listgr.pl
use warnings;
use strict;
while (my ($name, $passwd, $gid, $members) = getgrent) {
print "$gid: $name [$passwd] $members \n";
}
وبدلاً عن ذلك تعيد الدالة getgrent فقط أسم المجموعة في سياق scalar
#!/usr/bin/perl
# listgroups.pl
use warnings;
use strict;
my @groups;
while (my $name = getgrent) {
push @groups, $name;
}
print "Groups: @groups \n";
كما هو الحال مع getpwent تستعمل getgrent التي تسبب بفتح مقبض الملف داخلياً ( أو تفتح الإتصال الى سيرفر الـNIS or NIS+ في حالة طلب المعلومات من بعيد ) ، وتوفر الدوال getpwent, setgrent للإعادة مؤشر مقبض ملف المجموعة الى البداية ، و endgrent لإغلاق الملف ( أو أتصال الشبكة ) وتحرر المصادر المرتبطة .
وكذلك توفر البيرل وحـدة User::grent للتفاعل مع الدوال بشكل مماثل للوحدة User::pwent ولكن ليس من واجبها التأكد من معني الحقل التي هي ماتفعل وحدة User::pwent
#!/usr/bin/perl
# listbigr.pl
use warnings;
use strict;
use User::grent;
while (my $group = getgrent) {
print 'Name : ', $group->name, "\n";
print 'Password: ', $group->passwd, "\n";
print 'Group ID: ', $group->gid, "\n";
print 'Members : ', join(', ', @{$group->members}), "\n\n";
}
كما User::pwent (وكما اغلب الوحدات كالـNet::hostent ..الخ ) يمكن من إستيراد التاج :FIELDS للمتغيرات التي تحدث update بشكل آلي حينما أي من الدوال getgrent, getgrnam, or getgrgid تستدعى ، وهنا المثال السابق لإستعمال المتغيرات :
#!/usr/bin/perl
# listfldgr.pl
use warnings;
use strict;
use User::grent qw(:FIELDS);
while (my $group = getgrent) {
print 'Name : ', $gr_name, "\n";
print 'Password: ', $gr_passwd, "\n";
print 'Group ID: ', $gr_gid, "\n";
print 'Members : ', join(', ', @{$group->members}), "\n\n";
}
ولتحديد ايضاً المتغيرات المستوردة ان رغبت فقط في إستيراد بعض منهم :
use User::grent qw($gr_name $gr_gid);
في هذة الحالة الـoverriding للـgetgrent وماشابة فسوف لان يأخذ مكان ،لذلك سنحتاج الى إستدعى User::grent::getgrent بدلاً من إستدعى getgrent فقط أو عبور getgrent كما كابند في قائمة الإستيراد ، ولتجنب إستيراد إي شيء على الإطلاق نقوم بوضع قائمة الإستيراد فارغة فقط .
إستجواب الملفات مع stat و lstat
يمكن الإستغناء عن الكثير من معاملات الأختبار المتوفرة لدى البيرل لمعرفة تفاصيل اكثر عن الملفات بإستخدام الدوال stat أو lstat مباشرتاً ، التي تعيدان بعض التفاصيل والمعلومات لإسم الملف او لمقبض الملف المجهز كوسيط للدالتين ، الدالة lstat مشابة لدالة stat ماعدا في حالة الربط symbolic link أو مايعرف بالsoft link ، حيث تعيد stat تفاصيل الملف المشار الية بالـlink ، بينما تعيد lstat تفاصيل الـlink نفسة ، ومع الحالتين فسوف تعيد قائمة من 13 عنصر :
# stat filehandle into a list
@stat_info = stat FILEHANDLE;
# lstat file name into separate scalars
($dev, $ino, $mode, $nlink, $uid, $gid, $rdev, $size,
$time, $mtime, $ctime, $blksize, $blocks) = lstat $filename;
تعمل stat ايضاً مع مقبض الملف هكذا فأن المعلومات الراجعة تتأثر بنوع المقبض تحت ذلك الإستجواب :
my @stdin_info=stat STDIN; # stat standard input
opendir CWD, ".";
my @cwd_info=stat CWD; # stat a dir handle
ملاحظة :
لن تعمل lstat مع المقابض وسيتولد لنا تحذيرات عند محاولة لهذا العمل ، فالدالة لها معني فقط للمفات الفعلية لكؤنها تتعلق بالـsymbolic links ، مفهوم نظام الملفات file system لان يترجم الى مقابض الملفات .
فقد لاتتعرف قيم الثلاثة عشر دائماً أوقد لاتأخذ كل حالة بنفس المعني وذلك بسبب إختلاف البئية لنظام التشغيل او قد ترغب في استعمال البعض مع المقبض أو الملف لذالك فان الموديل File::stat المنجزة بواسطة الكائنات الموجهه تشير الى هذة القيم بواسطة إسم كل قيمة ، حيث القائمة الكاملة من القيم في الجدول إسفل يتضمن المعني ورقم الفهرس والاسم في العمود الاول هو إسم المتغير التقليدي لإستخدامات السابقة وإيضاً إسم الطريقة المنجزة بواسطة الموديل File::stat .
|
الطريقة |
الوصف |
| 0 |
dev |
رقم الجهاز لنظام الملف filesystem الذي يستقر فية الملف |
| 1 |
ino |
inode الملف |
| 2 |
mode |
نمط الملف متضمن نوع الملف وتصريح الملف |
| 3 |
nlink |
عدد مراجع hard (ليست symbolic) إلى inode التي تحت (هذا تأكد )إسم الملف |
| 4 |
uid |
معرف المستخدم user ID للمستخدم مالك الملف |
| 5 |
gid |
معرف المجموعة group ID للمجموعة التي تملك الملف |
| 6 |
rdev |
معرف الجهاز device ID ( للملفات الخاصة فقط block and character ) |
| 7 |
size |
حجم الملف بالبايت bytes |
| 8 |
atime |
زمن أخر وصول الى الملف في الثانية |
| 9 |
mtime |
زمن أخر تعديل في الثانية |
| 10 |
ctime |
زمن أخر تغير inode في الثانية |
| 11 |
blksize |
حجم الـblock المفضلة لنظام الملف filesystem |
| 12 |
blocks |
عدد الـبولكات blocks الموطنة للملف ،فمثلاً ينتج منة بحجم موطن في نظام الملف file system قدرة
$stat_info[11]*$stat_info[12]
على اي حال فأن الحجم الفعلي للملف من ناحية محتوياتة ستكون أقل من هذا كما سوف يملأ جزيئاً الكتلة الأخيرة—بإستخدام $stat_info[7] (size) لإيجاد ذلك
|
تعيد stat العديد من القيم المتعلقة با “inode” الملف ، inode الملف في اليونكس هو معرف ID عددي يوضع بواسطة نظام الملف file system والذي سيكون معرفة “true” مع إسم الملف لكي يكون فقط alias علية، بمعني الأرصفة التي تدعم inode فأن أكثر من أسم ملف واحد قد يشير الى نفس الملف، كذلك تعيد قيمة nlink عدد الـhard links التي قد تكون أكثر من أسم واحد (وليس أقل ويعني ذلك بأن inode ليس لديها إسماء ملفات لكي تشير اليها ) ، وتشير قيمة ctime الى أخر زمن لتغير عقدة الملف ، فقد تعني زمن الإنشاء في أغلب الأحيان ، بالمقابل فأن زمن الوصول والتعديل يشير الى الوصول الفعلي للملف .
بعض القيم على الأرصفة الاخرى غير معرفة أو بلامعني فمثلاً الونيدوز رقم الجهاز متعلق الى رسائلة المحرك drive letter ، وليس هنالك inode وقيمة nlink دائماً 1 ،وكذلك uid and gid بالقيم 0 ولايعد شيء locksize or blocks مع ذلك mode مفيد لمعرفة نوع الملف ( نوع الملف اما يكون plain أو مجلد او اختصار للملف symbolic link أو أنبوب أو مقبس أو جهاز ..الى غير ) في Windows NT/2000/XP تعطي الصلاحيات دائماً 777 (نظام الونيدوز اكثر تعقيد في الصلاحيات من نظام اليونكس) يمكن استخدام الوحدات Win32::FileSecurity and Win32::FilePermissions ، كذلك في شكل من الاشكال الوصول الى القيمة المعادة بواسطة stat غير أنيق فمثلاُ لمعرفة حجم الملف
$size = (stat $filename)[7];
#Or, printing it out:
print ((stat $filename)[7]); # need to use extra parentheses with print
وحـدة File::stat تودي نفس الغرض وبشكل مبسط ومنسق وتستعمل كلتا الدالتين stat and lstat عن طريق عمل overriding لهم مع الدالة الخاصة التي تعيد كائنات stat بدلاً من القائمة ومن ثم إستخدام احدى الطرق مع هذة الكائنات بنفس اسم القيم الراجعة في السابق ، فمثلاً لإستخدام الطرق size, blksize, and blocks لإعادة حجم الملف المدعم على سطر الاوامر :
#!/usr/bin/perl
# filesize.pl
use warnings;
use strict;
use File::stat;
print "Enter filename: ";
my $filename = <>;
chomp $filename;
if (my $stat = stat $filename) {
print "'$filename' is ", $stat->size,
" bytes and occupies ", $stat->blksize * $stat->blocks,
" bytes of disc space \n";
} else {
print "Cannot stat $filename: $| \n";
}
يمكن تعديل إستخدام الطرق الكائن وإستيراد 13 متغير التي تحوي النتائج عن طريق إظافة قائمة الإستيراد :FIELDS ، فكل متغير سوف يأخذ نفس الاسم يتقدمة النص st_
#!/usr/bin/perl
# filesizefld.pl
use warnings;
use strict;
use File::stat qw(:FIELDS);
print "Enter filename: ";
my $filename = <>;
chomp($filename);
if (stat $filename) {
print "'$filename' is ", $st_size,
" bytes and occupies ", $st_blksize * $st_blocks,
" bytes of disc space \n";
} else {
print "Cannot stat $filename: $| \n";
}
يمكن إستخدام النسخ الأصلية للدالتين stat and lstat بواسطة تقديمهم مع إسم حزمة CORE::
use File::stat;
...
my @new_stat = stat $filename; # use new 'stat'
my @old_stat = CORE::stat $filename; # use original 'stat'
فبدلاً عن ذلك يمكن منع الـoverride من الحدوث عن طريق جلب قائمة إستيراد فارغة .
use File::stat qw(); # or '', etc.
الان يمكن من إستخدام الطرق stat و lstat بتحديهم مع أسم الحزمة
my $stat = File::stat::stat $filename;
print "File is ", $stat->size(), " bytes \n";
تغير صفات الملف
Changing File Attributes
هناك ثلاثة أنواع أساسية للتغير صفات الملف التي نستطيع من خلاها القراءة أو التعديل ، كتغير الملكية وصلاحيات الوصول وتغير زمن الوصول والتعديل ، وتوفر البيرل دوال الصلاحيات المتعلقة بالملف كالدوال chmod و chgrp في أرصفة اليونكس وفي الأنظمة الاخرى التي تدعم مفهوم الصلاحيات والملكية ، وترتبط
الملكية والصلاحيات بشكل معقد ومجتمعة الى قيمة mode المعادة بواسطة stat
ملكية الملف :
مفهوم ملكية الملف يعتمد على مفهوم الرصيف المصمم علية نظام التشغيل ، و تعالج بشكل مشابة لليونكس حيث لدى الملفات مالك ممثلة بواسطة file’ s user ID ومالك المجموعة ممثلة بواسطة file’ s group ID ، وكل منهم يتعلق بمختلف صلاحيات الملف ، لذلك فأن المستخدم قد يكون لدية القدرة على القراءة والكتابة في الملف بينما بقية المستخدمين في نفس المجموعة قد يحصلون على قراءة الملف فقط والبقية قد لايحصلون على اي شيء ويعتمد ذلك على إعدادءات صلاحيات الملف .
تعالج ملكية الملف بواسطة الدالة chown التي تعالج وتماثل كلتا الإستدعاءات للنظام chown و chgrp ،وتأخذ هذة الدالة على الاقل ثلاثة وسطاء وهم user ID و group ID والملف أو اكثر من ملف للتغير ملكيتة :
my @successes = chown $uid, $gid, @files;
حيث تعيد عدد الملفات التي تغيرت بنجاح وأن كان الملف المعطى واحد الى الدالة فسوف يسمح لنا بإختبار النجاح او الفشل عن طريق الشرط :
unless (chown $uid, $gid, $filename) {
die "chown failed: $! \n";
}
ولتغير ملكية الملف للمستخدم فقط أو الى مجموعة اخرى نضع -1 كقيمة للوسيط الاخر ، على سبيل المثال الدالة chgrp تماثل :
sub chgrp {
return chown(shift, -1, @_);
}
لاحظ ذلك على اغلب الانظمة ( فأن اكثر الانظمة تدرك ملكية الملف في المكان الاول )، وعادة مستخدم الروت هو من يقوم بتغير المستخدم الذي يملك الملف ، مع ذلك فأن المجموعة يمكن ان تتغير الى مجموعة اخرى التي نفس المستخدم ينتمي اليها أو قد تكون مختلفة عنة تماماً ، ومن المحتمل لأتقدير اذا كان تغير الملكية مسموح بة نقوم بإستدعى الدالة sysconf :
my $chown_restricted = sysconf(_PC_CHOWN_RESTRICTED);
فأن إعادة قيمة true فأن الدالة chown غير مسموحة
الدالة chown تأخذ user ID أو group ID وليس اسم المستخدم والمجموعة ، ولإستخراج الـuser ID من الاسم نستعمل الدالة getpwnam ، وعلى نفس النمط لستخراج الـ group ID من اسم المجموعة مع الدالة getgrnam ، وبدلاً من ذلك يمكن إستعمال الدالة getpwent لإستراجاع مستخدم واحد والدالة getgrent لإستراجاع مجموعة واحدة فعلى سبيل المثال السكربت التالي يصنع جدولاً من IDs المستخدمين والمجموعة التي المنتمية ونستطيع بعد ذلك من استعمال الدالة chown :
#!/usr/bin/perl
use warnings;
use strict;
# get user names and primary groups
my (%users, %usergroup);
while (my ($name, $passwd, $uid, $gid) = getpwent) {
$users{$name} = $uid;
$usergroup{$name} = $gid;
}
# get group names and gids
my (%groups, @groups);
while (my ($name, $passwd, $gid) = getgrent) {
$groups{$name} = $gid;
$groups[$gid] = $name;
}
# print out basic user and group information
foreach my $user (sort {$users{$a} <=> $users{$b}} keys %users) {
print "$users{$user}: $user, group ", $usergroup{$user},
" (", $groups[$usergroup{$user}], ")\n";
}
صلاحيات الملف:
تؤفر البيرل دالتين للصلاحيات الملف وهم chmod و umask المتضمنة في أرصفة اليونكس ولكن ليس الونيدوز التي لديها وحـدات اخرى للحماية الملفات كالـوحدة Win32::FileSecurity و Win32::FilePermissions ، فالدالة chmod تسمح بإعطى صلاحية للملف هكذا فأن لدى الصلاحية ثلاثة أصناف وهم المستخدم (مالك الملف) و المجموعة والاخرين لأي شخص سواء المالك او عضوء في مجموعة مالك الملف ، ولكل صنف لكل ملف لدية الثلاث الصلاحيات( القراءة او الكتابة او التنفيذ) .
تمثل الدالة chmod (إختصار للـ change mode ) بتسعة قيم ( 3 الأصناف × 3 الصلاحيات ) بإختلاف العلم العددي لهم والتي يوضع سويتاً بشكل ثلاثة إرقام ثمانية الترميز ولكل رقم يقابل الصنف الخاص به ، فقيم العلم ضمن كل رقم هي :
4 لصلاحية القراءة
2 لصلاحية الكتابة
1 لصلاحية التنفيذ
وكما هو موضح في الامثلة التالية ولها قيمة 0 في المقدمة للإشارة للترميز القيم بالثماني
0200 Owner write permission
0040 Group read permission
0001 Other execute permission
نلاحظ ان مجموع الصلاحيات الثلاثة للصنف هي 7 ولهذا السبب يستخدم الترميز الثماني عن غيرة للسهولة ،فمثلاً بوضع 0700 فسوف تقوم بجمع الصلاحيات الثالث للمالك اي القراءة والكتابة والتنفيذ وكذلك مع الصناف الاخرى فمثلاً 0751 التي هي كما لو كانت 0400 + 0200 + 0100 + 0040 + 0010 + 0001.
وبعد توضيح علم الصلاحيات فالدالة chmod تأخذ علم الصلاحيات كأول وسيط لها ثم تطبق على الملف او اكثر من ملف مع الوسيط الثاني:
chmod 0751, @files;
وكما هو الحال مع chown في السابق للعدد الملفات التي نجحت بإعطها التصاريح حيث تعيد صفر اذا كانت الملفات لم تغير بشكل ناجح فمثلاً لمعرفة اذا لم يغير الملف فالدالة سوف تعيد الناتج الى الشرط :
unless (chmod 0751, $file) {
die "Unable to chmod: $! \n";
}
الدالة umask تخصر في اليونكس ("user file-creation mode mask") لتغير الصلاحيات الافتراضية في حين أو عند إنشاء البيرل ملفات جديدة ، فالـbits في الـumask لها معني معاكس للصلاحيات المارة الى الدالة chmod فبعدم وضع الـbits المطابقة في الصلاحية عندما الملف ينشاء بواسطة open او sysopen فسوف توضع الصلاحية الافتراضية وعند أستخدام للدالتين open, sysopen أربعة وسطاء لإعطى صلاحيات mask للنفسها في رابع وسيط اما عن طريق الترميز الثماني أو بوسطة الأعلام المتجتمة المستوردة .
هكذا عند ضبط bits الصلاحية الى الدالة umask فسوف تضبط بدلاً من الافتراضي ، والجدول اسفل bits الصلاحية المستخدمة مع الدالة umask
| رقم umask |
صلاحية الملف |
| 0 |
قراءة وكتابة |
| 1 |
قراءة وكتابة |
| 2 |
قراءة فقط |
| 3 |
قراءة فقط |
| 4 |
كتابة فقط |
| 5 |
كتابة فقط |
| 6 |
لاقراءة ولاكتابة |
| 7 |
لاقراءة ولاكتابة |
تعرف الدالة umask صلاحيات الوصول وتستدعئ بدون وسيط وتعيد القيمة الحالية (المؤرثة من الشل ) من عمل umask وتوضع نموذجياً الى القيمة 002 ( القناع المزيف لصلاحية الكتابة للاخرين) أوالى القيمة 022 ( القناع المزيف لصلاحيات الكتابة للمجموعة والاخرين ) :
$umask = umask;
قد تستدعى الدالة umask بوسيط واحد عددي للتقدير التقليدي في الثماني :
umask 022;
ليست فكرة جيدة ان نقوم بتجاوز الـumask بشكل واضح لكؤن أن المستخدم قد يضع أكثر من قيمة مقيدة ، فالأفضل جمع التصاريح التي نرغب لتقيد مع الـumask الموجود بإستعمال bitwise OR على سبيل المثال :
umask (022 | umask);
الدالة open تستعمل الصلاحية 0666 ( للقراءة والكتابة لكل الإصناف ) بينما sysopen تسمح بالإصلاحيات لكي تحدد عند إستدعها ، وعند عمل umask فلن نحتاج لتضمين الصلاحية مرة اخرى للدالة sysopen .
أزمنة الوصل للملف
تزود الدالة utime المقدرة لتغيير وقت أخر وصول وأخر تعديل للملف أو الملفات ، وتأخذ هذة الدالة على الاقل ثلاثة وسطاء وهم : زمن الوصول الجديد في الثواني منذ 1970/1/1 00:00:00 وتأخذ زمن التعديل الجديد ايضاً في الثواني ومن ثم الملف او قائمة الملفات لتغير أوقاتهم فعلى سبيل المثال :
my $onedayago=time - 24*60*60;
utime $onedayago, time(), "myfile.txt", "my2ndfile.txt";
سيضع الملف المحدد في المثال السابق الى زمن أخر وصول بالضبط منذ يوم ، وزمن أخر تعديل في التمام في هذا الوقت ، ويمكن من تحديد undef في بيرل 5.8 والتي تعني في التمام في هذا الوقت ، لذلك لمحاكاة اوامر اليونكس على كل ملفات C or C++ في المجلد الحالي يمكن إستعمال
utime undef, undef, <*.c>, <*.cpp>
الربط وفك الربط والحذف وإعادة تسمية الملفات
يمكن من معالجة أسماء الملفات مباشرتاً مع الدوال الداخلية link and unlink ، وتزود هذة الدوال المقدرة لتعديل مدخلات الملفات في نظام الملف filesystem عن طريق أنشاء واحداًُ جديد أو بحذف واحداًُ موجود ،وليست تلك الدوال نفس عملية إنشاء وحذف الملفات على اي حال فعلى الأرصفة التي تدعم مفهوم الربط تنشاء الدالة link رابطاً جديد (مدخل في نظام الملف filesystem ) للملف الموجود التي لاتقوم بإنشاء نسخة copy ( التي مايقوم بهذا نظام الونيدوز ) ، على نفس النمط تحذف unlink أسم الملف من نظام الملف filesystem ولكن أذا الملف لدية أكثر من رابط فسوف يكون لدية أكثر من أسم للملف فسوف يبقئ الملف ولان يتم حذفة وهذة النقطة مهمة لأن ذلك يؤدي الى التشويش في أغلب الاوقات .
Linking Files
تعمل الدالة link على أنشاء رابط جديد (يعرف أيضاً بالhard link لكي يتم تميزة عن الروابط soft أو ماتعرف بالsymbolic link ) لإسم الملف ، وتعمل هذة الدالة على الأرصفة التي توفر الامكانية من عمل العديد من hard links الى الملف نفسة :
if (link $currentname, $newname) {
print "Linked $currentname to $newname ok \n";
} else {
warn "Failed to link: $! \n";
}
لانستطيع من استخدام الدالة link في أنشاء رابط للمجلدات مع أنها تنشاء الروابط لجميع أنواع الملفات الاخرى ويمكن من أنشاء symbolic links للمجلدات فقط وليست مع hard links ،أضافتاً لانستطيع من أنشاء hard links بين مختلف أنظمة الملف filesystems ولابين المجلدات على بعض الأنظمة الملف filesystems (كال AFS )، في أنظمة اليونكس تعطي الدالة link أثنين أسماء في filesystem وبنفس inode لهما ، أما على الونيدوز وعلى filesystems التي لاتدعم هذا المفهوم فسوف تنشاء نسخة copy من الملف الأصلي .
وفي حالة نجاح الدالة بالربط فسوف تعيد true وإنشاء أسم الملف جديد الى مدخل filesystem وستحمل الرابط الجديد بنفس صلاحيات وملكية الملف الاصلي ويصبح لدى الملف أسمين يشيارن الية وبتعديل أحدهم فسوف يعدل محتوى الملف فوراً ولكن نستطيع من التغير عن طريق الدوال الداخلية chmod and chown فعلى سبيل المثال لإنشاء entry pointللقراءة فقط والقراءة-كتابة الى نفس البيانات
Deleting and Unlinking Files
نظير الربط هو فك الربط ،ويمكن للملفات من فك رابطها بواسطة الدالة unlink التي تأخذ واحد أو أكثر من أسم ملف كالباراميترات لها ، وأن لايوجد لديها أي أسم للملف فسوف تستعمل محتوى المتغير الخاص $_ :
unlink $currentname; # single file
foreach (<*.*>) {
unlink if /\.bak$/; # unlink $_ if it ends '.bak'
}
unlink <*.bak>; # the same, via a file glob
unlink بسيطة لحذف الملف ولكن ليس من الضروة أستخدامها لحذف الملفات بسبين ،أولاً لانها على الأرصفة التي لاتدعم فك ربط unlinking أذاكان لدى الملف أكثر من رابط واحد فسوف تبقى الأسماء الاخرى متؤفرة في filesystem ، وبالرغم من أننا لا نستطيع من إيجاد الأسماء للروابط الاخرى ولكن نستيطع فقط إيجاد كم لدي الملف روابط عن طريق stat للتأكد من أن unlink قد حذفت الملف أو فقط قأمت بإحذف أحد روابطها :
my $links = (stat $filename)[3];
# Or more legibly with the File::stat module
my $stat = new File::stat($filename);
my $links = $stat->nlink;
ثانياً على الأرصفة التي تدعمها (أنظمة اليونكس) فأذا كأنت اي عملية مفتوح لديها مقبض الملف للملف فأن سوف يبقى طالما كأن مقبض الملف مفتوح ، وهذا يعني حتي وأن حذفت جميع الروابط للملف عن طريق unlink فمازال الملف موجود ونستطيع القراءة منة أو الكتابة أو نسخ محتواه الى ملف اخر ،وعلى الأرصفة الاخرى كالونيدوز فأن البيرل سترفض محاولة unlink للملف طالما الملف مفتوح مقبضة لذلك عليك التأكد أولاً من إغلاق المقبض قبل حذف الملف
لن تعمل الدالة unlink للمجلدات مالم يجتمع الثلاثة المعايير :العمل على اليونكس وأعطاء البيرل العلم -U ولدينا أمتيزات الروت ، رغم ذلك فهو من غير المستحسن عمل ذلك بسبب انة سوف يحذف مايحتوية المجلد بضمن أي مجلد فرعي لة المتدرج في filesystem ولكنة لايعود على ما كأن علية من قبل وبنفس الفضاء المستغل على القرص ، وبدلاً من ذلك فسوف يظهرون في مجلد lost+found في كل مرة تقوم بإنجاز الفحص عن طريق fsck filesystem check للإرجاع العمل الذي لم نكن للنقصدة ، وعلى اي حال الامر rmdir ينجز هذا العمل وكذلك الدالة rmtree من File::Path التي تتضمن مع العديد من المجلدات .
Output
Skipper: Hey there, Professor!
Gilligan: Hi, Professor!
Figure 3-1. Page output produced by hard-coded text and
XHTML.
osaPage_Load
Sunday, March 25, 2007
HHH
| Field Name |
Data Type |
Field Size |
Example Data |
| BookID (Key) |
Text |
5 |
DB222 |
| BookType |
Text |
10 |
Database |
| BookTitle |
Text |
50 |
Databases in Depth |
| BookAuthor |
Text |
20 |
C. J. Date |
| BookDescription |
Memo |
|
In Database . |
| BookPrice |
Currency |
|
$29.95 |
| BookQty |
Number |
Long Integer |
6 |
| BookSale |
Yes/No |
|
True (checked) or False |
Books.zip
OSAMA